#include "Python.h"
#include <structmember.h>
#include <string.h>
#include "tft.h"

typedef struct{
    PyObject_HEAD
    struct tft tft_config;
} st7735s_ST7735SObject;

static PyObject* ST7735S_new(PyTypeObject* type,PyObject* args,PyObject* kwds){
    st7735s_ST7735SObject* self;
    self=(st7735s_ST7735SObject*)type->tp_alloc(type,0);
    if(self!=NULL){
        self->tft_config.spidev=NULL;
        self->tft_config.dc=7;
        self->tft_config.res=11;
        self->tft_config.speed=100000000;
        self->tft_config.width=128;
        self->tft_config.height=128;
    };
    return (PyObject*)self;
}

static int ST7735S_init(st7735s_ST7735SObject* self,PyObject* args,PyObject* kwds){
    self->tft_config.fd=0;
    static char *kwlist[]={"spidev","DC","RES","SPEED","width","height",NULL};
    if(!PyArg_ParseTupleAndKeywords(args,kwds,"sii|iii",kwlist,&self->tft_config.spidev,&self->tft_config.dc,&self->tft_config.res,&self->tft_config.speed,&self->tft_config.width,&self->tft_config.height))return -1;
    TFT_Init(&self->tft_config);
    return 0;
}

static void ST7735S_dealloc(st7735s_ST7735SObject* self){
    TFT_Close(&self->tft_config);
    Py_TYPE(self)->tp_free((PyObject*)self);
}

static PyObject* ST7735S_Reset(st7735s_ST7735SObject* self){
    TFT_Reset(&self->tft_config);
    Py_INCREF(Py_None);
    return Py_None;
}

static PyObject* ST7735S_Clear(st7735s_ST7735SObject* self,PyObject* args){
    int Color;
    if(!PyArg_ParseTuple(args,"i",&Color)) {
        return NULL;
    };
    TFT_Clear(&self->tft_config,Color);
    Py_INCREF(Py_None);
    return Py_None;
}

static PyObject* ST7735S_DrawPoint(st7735s_ST7735SObject* self,PyObject* args){
    int x,y,Color;
    if(!PyArg_ParseTuple(args,"iii",&x,&y,&Color)) {
        return NULL;
    };
    TFT_DrawPoint(&self->tft_config,x,y,Color);
    Py_INCREF(Py_None);
    return Py_None;
}

static PyObject* ST7735S_DrawRect(st7735s_ST7735SObject* self,PyObject* args){
    int x1,y1,x2,y2,Color;
    if(!PyArg_ParseTuple(args,"iiiii",&x1,&y1,&x2,&y2,&Color)) {
        return NULL;
    };
    TFT_DrawRect(&self->tft_config,x1,y1,x2,y2,Color);
    Py_INCREF(Py_None);
    return Py_None;
}

static PyObject* ST7735S_DrawLine(st7735s_ST7735SObject* self,PyObject* args){
    int x1,y1,x2,y2,Color;
    if(!PyArg_ParseTuple(args,"iiiii",&x1,&y1,&x2,&y2,&Color)) {
        return NULL;
    };
    TFT_DrawLine(&self->tft_config,x1,y1,x2,y2,Color);
    Py_INCREF(Py_None);
    return Py_None;
}

static PyObject* ST7735S_DrawChar(st7735s_ST7735SObject* self,PyObject* args){
    int x,y,ascii_code,front_color,back_color;
    if(!PyArg_ParseTuple(args,"iiiii",&x,&y,&ascii_code,&front_color,&back_color)) {
        return NULL;
    };
    TFT_DrawChar(&self->tft_config,x,y,ascii_code,front_color,back_color);
    Py_INCREF(Py_None);
    return Py_None;
}

static PyObject* ST7735S_DrawString(st7735s_ST7735SObject* self,PyObject* args){
    char* string;
    int x,y,front_color,back_color;
    if(!PyArg_ParseTuple(args,"iisii",&x,&y,&string,&front_color,&back_color)) {
        return NULL;
    };
    TFT_DrawString(&self->tft_config,x,y,string,front_color,back_color);
    Py_INCREF(Py_None);
    return Py_None;
}

static PyObject* ST7735S_Close(st7735s_ST7735SObject* self,PyObject* args){
    TFT_Close(&self->tft_config);
    Py_INCREF(Py_None);
    return Py_None;
}

static PyMethodDef ST7735S_methods[] = {
    {"Reset",(PyCFunction)ST7735S_Reset,METH_NOARGS,NULL},
    {"Clear",(PyCFunction)ST7735S_Clear,METH_VARARGS,NULL},
    {"DrawPoint",(PyCFunction)ST7735S_DrawPoint,METH_VARARGS,NULL},
    {"DrawRect",(PyCFunction)ST7735S_DrawRect,METH_VARARGS,NULL},
    {"DrawLine",(PyCFunction)ST7735S_DrawLine,METH_VARARGS,NULL},
    {"DrawChar",(PyCFunction)ST7735S_DrawChar,METH_VARARGS,NULL},
    {"DrawString",(PyCFunction)ST7735S_DrawString,METH_VARARGS,NULL},
    {NULL,NULL,0,NULL}
};

static PyTypeObject st7735s_ST7735SType={
    PyVarObject_HEAD_INIT(NULL,0)
    .tp_name="st7735s.ST7735S",
    .tp_basicsize=sizeof(st7735s_ST7735SObject),
    .tp_itemsize=0,
    .tp_flags=Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
    .tp_new=ST7735S_new,
    .tp_init=(initproc)ST7735S_init,
    .tp_dealloc=(destructor)ST7735S_dealloc,
    .tp_methods=ST7735S_methods
};

static PyObject* pyfunc_c888to565(PyObject* self,PyObject* args){
    char* color888_s;
    unsigned int color888;
    unsigned char r,g,b;
    unsigned int color565;
    if(!PyArg_ParseTuple(args,"s",&color888_s)) {
        return NULL;
    };
    if(*color888_s!='#'||strlen(color888_s)!=7){
        return NULL;
    };
    color888=strtol(color888_s+1,NULL,16);
    r=color888>>16;
    g=(color888>>8)&0xFF;
    b=color888&0xFF;
    color565=((r>>3)<<11)|((g>>2)<<5)|(b>>3);
    return Py_BuildValue("i",color565);
}

static PyMethodDef module_methods[]={
    {"c888to565",pyfunc_c888to565,METH_VARARGS,NULL},
    {NULL,NULL,0,NULL}
};

#if PY_MAJOR_VERSION > 2
static struct PyModuleDef st7735s_module={
    PyModuleDef_HEAD_INIT,
    "st7735s",
    NULL,
    -1,
    module_methods
};
#endif

#if PY_MAJOR_VERSION > 2
PyMODINIT_FUNC PyInit_st7735s(void)
#else
PyMODINIT_FUNC initst7735s(void)
#endif
{
    #if PY_MAJOR_VERSION > 2
        PyObject* module=PyModule_Create(&st7735s_module);
    #else
        PyObject* module=Py_InitModule("st7735s",module_methods);
    #endif
    PyModule_AddObject(module,"RED",Py_BuildValue("i",0xF800));
    PyModule_AddObject(module,"GREEN",Py_BuildValue("i",0x00E0));
    PyModule_AddObject(module,"BLUE",Py_BuildValue("i",0x001F));
    PyModule_AddObject(module,"WHITE",Py_BuildValue("i",0xFFFF));
    PyModule_AddObject(module,"BLACK",Py_BuildValue("i",0x0000));
    PyModule_AddObject(module,"YELLOW",Py_BuildValue("i",0xFFE0));
    PyModule_AddObject(module,"GRAY0",Py_BuildValue("i",0xEF7D));
    PyModule_AddObject(module,"GRAY1",Py_BuildValue("i",0x8410));
    PyModule_AddObject(module,"GRAY2",Py_BuildValue("i",0x4208));

    if(PyType_Ready(&st7735s_ST7735SType)<0)return;
    Py_INCREF(&st7735s_ST7735SType);
    PyModule_AddObject(module,"ST7735S",(PyObject*)&st7735s_ST7735SType);

    #if PY_MAJOR_VERSION > 2
        return module;
    #else
        return;
    #endif
}